package helipay.api.jedis;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;

/**
 * Redis操作接口一致性Hash实现，80%命中率，适合动态添加server
 * 
 */
@Component
@Scope("singleton")
public class ShardingRedisAPI {

	private static Log logger = LogFactory.getLog(ShardingRedisAPI.class);

	@Value("${redis.maxActive}")
	private String maxActive;
	@Value("${redis.maxIdle}")
	private String maxIdle;
	@Value("${redis.maxWait}")
	private String maxWait;
	@Value("${redis.testOnBorrow}")
	private String testOnBorrow;

	@Value("${redis0.host}")
	private String host0;
	@Value("${redis0.port}")
	private String port0;

	@Value("${redis1.host}")
	private String host1;
	@Value("${redis1.port}")
	private String port1;

	@Value("${redis2.host}")
	private String host2;
	@Value("${redis2.port}")
	private String port2;

	@Value("${redis3.host}")
	private String host3;
	@Value("${redis3.port}")
	private String port3;

	private ShardedJedisPool pool = null;

	private List<JedisShardInfo> getJedisShardInfos() {
		List<JedisShardInfo> jedisShardInfos = new ArrayList<JedisShardInfo>();

		if (StringUtils.isNotBlank(host0) && Integer.valueOf(port0) > 0) {
			jedisShardInfos.add(new JedisShardInfo(host0, Integer.valueOf(port0)));
		}
		if (StringUtils.isNotBlank(host1) && Integer.valueOf(port1) > 0) {
			jedisShardInfos.add(new JedisShardInfo(host1, Integer.valueOf(port1)));
		}
		if (StringUtils.isNotBlank(host2) && Integer.valueOf(port2) > 0) {
			jedisShardInfos.add(new JedisShardInfo(host2, Integer.valueOf(port2)));
		}
		if (StringUtils.isNotBlank(host3) && Integer.valueOf(port3) > 0) {
			jedisShardInfos.add(new JedisShardInfo(host3, Integer.valueOf(port3)));
		}
		return jedisShardInfos;
	}

	public void init() {
		logger.info("init");

		JedisPoolConfig config = new JedisPoolConfig();
		config.setMaxActive(Integer.valueOf(maxActive));
		config.setMaxIdle(Integer.valueOf(maxIdle));
		config.setMaxWait(Integer.valueOf(maxWait));
		config.setTestOnBorrow(Boolean.valueOf(testOnBorrow));

		pool = new ShardedJedisPool(config, getJedisShardInfos());
	}

	public void destroy() {
		logger.info("destroy");

		pool.destroy();
	}

	/**
	 * 构建redis连接池
	 * 
	 * @return JedisPool
	 */
	public ShardedJedisPool getPool() {
		return pool;
	}

	/**
	 * 返还到连接池
	 * 
	 * @param pool
	 * @param redis
	 */
	public void returnResource(ShardedJedisPool pool, ShardedJedis redis) {
		if (pool != null) {
			pool.returnResource(redis);
		}
	}

	public void returnBrokenResource(ShardedJedisPool pool, ShardedJedis redis) {
		if (pool != null) {
			pool.returnBrokenResource(redis);
		}
	}

	public boolean set(String key, String value) {

		ShardedJedisPool pool = null;
		ShardedJedis jedis = null;

		try {
			pool = getPool();
			jedis = pool.getResource();

			jedis.set(key, value);
		} catch (Exception e) {
			returnBrokenResource(pool, jedis);
			logger.error(e.getMessage(), e);
		} finally {
			returnResource(pool, jedis);
		}

		return true;
	}

	/**
	 * 获取数据
	 * 
	 * @param key
	 * @return
	 */
	public String get(String key) {
		String value = null;

		ShardedJedisPool pool = null;
		ShardedJedis jedis = null;

		try {

			pool = getPool();
			jedis = pool.getResource();
			value = jedis.get(key);

		} catch (Exception e) {
			returnBrokenResource(pool, jedis);
			logger.error(e.getMessage(), e);
		} finally {
			returnResource(pool, jedis);
		}

		return value;
	}

}
